//! # 配置加载器模块
//!
//! 提供了灵活的配置文件加载和解析功能，支持多种配置格式的自动识别和解析。
//! 该模块是配置管理系统的核心组件，负责将外部配置文件转换为应用可用的配置对象。

use crate::RustCloudConfig;
use serde::{Deserialize, Serialize};
use std::fs;
use std::path::Path;

/// 配置文件格式枚举
///
/// 定义了 RustCloud 支持的所有配置文件格式。每种格式都有其特定的优劣势和适用场景。
///
/// # 支持的格式
///
/// * **TOML** - Tom's Obvious Minimal Language，人类友好的配置语言
///   - 优势：语法简洁、清晰、易于理解和编辑
///   - 适用场景：手工维护的配置文件
///
/// * **YAML** - YAML Ain't Markup Language，用缩进表示层次的数据格式
///   - 优势：结构清晰、支持复杂数据结构、可读性好
///   - 适用场景：复杂的配置文件、DevOps 工具链
///
/// * **JSON** - JavaScript Object Notation，轻量级的数据交换格式
///   - 优势：标准化、广泛支持、机器生成友好
///   - 适用场景：程序生成的配置、API 交互
///
/// # 使用示例
///
/// ```rust
/// use rustcloud_config::ConfigFormat;
///
/// // 根据文件扩展名自动识别格式
/// assert_eq!(ConfigFormat::from_extension("toml"), Some(ConfigFormat::Toml));
/// assert_eq!(ConfigFormat::from_extension("yaml"), Some(ConfigFormat::Yaml));
/// assert_eq!(ConfigFormat::from_extension("json"), Some(ConfigFormat::Json));
///
/// // 根据文件路径自动识别格式
/// let format = ConfigFormat::from_path("config.yaml").unwrap();
/// assert_eq!(format, ConfigFormat::Yaml);
/// ```
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub enum ConfigFormat {
    /// TOML 格式（.toml）
    Toml,
    /// YAML 格式（.yaml, .yml）
    Yaml,
    /// JSON 格式（.json）
    Json,
}

impl std::fmt::Display for ConfigFormat {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            ConfigFormat::Toml => write!(f, "toml"),
            ConfigFormat::Yaml => write!(f, "yaml"),
            ConfigFormat::Json => write!(f, "json"),
        }
    }
}

impl ConfigFormat {
    /// 根据文件扩展名获取配置格式
    pub fn from_extension(extension: &str) -> Option<Self> {
        match extension.to_lowercase().as_str() {
            "toml" => Some(ConfigFormat::Toml),
            "yaml" | "yml" => Some(ConfigFormat::Yaml),
            "json" => Some(ConfigFormat::Json),
            _ => None,
        }
    }
    
    /// 根据文件路径获取配置格式
    pub fn from_path<P: AsRef<Path>>(path: P) -> Option<Self> {
        path.as_ref()
            .extension()
            .and_then(|ext| ext.to_str())
            .and_then(ConfigFormat::from_extension)
    }
}

/// 配置加载器
///
/// 负责从文件系统加载和解析配置文件的核心组件。支持多种配置格式，
/// 提供统一的加载接口，并能够生成默认的配置文件模板。
///
/// # 功能特性
///
/// * **智能格式识别** - 根据文件扩展名自动识别配置格式
/// * **错误处理** - 提供详细的错误信息，帮助快速定位问题
/// * **默认配置生成** - 能够生成开箱即用的示例配置文件
/// * **内容解析** - 支持从字符串内容直接解析配置
///
/// # 使用流程
///
/// 1. **创建加载器** - 指定配置文件路径和格式
/// 2. **加载配置** - 调用 `load()` 方法加载配置
/// 3. **验证配置** - 验证加载的配置是否有效
/// 4. **使用配置** - 将配置应用到应用程序中
///
/// # 完整使用示例
///
/// ```rust,no_run
/// use rustcloud_config::{ConfigLoader, ConfigFormat};
///
/// # fn main() -> Result<(), String> {
/// // 方式1：自动识别文件格式
/// let loader = ConfigLoader::from_path("config.yaml")?;
/// let config = loader.load()?;
///
/// // 方式2：手动指定文件格式
/// let loader = ConfigLoader::new("config.toml", ConfigFormat::Toml);
/// let config = loader.load()?;
///
/// // 生成默认配置文件
/// let loader = ConfigLoader::new("default.yaml", ConfigFormat::Yaml);
/// loader.create_default_config()?;
///
/// // 从字符串解析配置
/// let yaml_content = "application:\n  name: my-service";
/// let config = loader.parse_content(yaml_content)?;
/// # Ok(())
/// # }
/// ```
///
/// # 错误处理
///
/// 加载器提供详细的错误信息，包括：
/// * 文件不存在或权限不足
/// * 文件格式错误或语法错误
/// * 不支持的文件格式
/// * 配置验证失败
pub struct ConfigLoader {
    /// 配置文件格式
    format: ConfigFormat,
    /// 配置文件路径
    path: String,
}

impl ConfigLoader {
    /// 创建新的配置加载器
    pub fn new(path: impl Into<String>, format: ConfigFormat) -> Self {
        Self {
            path: path.into(),
            format,
        }
    }
    
    /// 根据文件路径自动推断格式创建加载器
    pub fn from_path(path: impl Into<String>) -> Result<Self, String> {
        let path_str = path.into();
        let path_ref = Path::new(&path_str);
        let format = ConfigFormat::from_path(path_ref)
            .ok_or_else(|| format!("Unsupported config file format: {:?}", path_ref))?;
        
        Ok(Self::new(path_str, format))
    }
    
    /// 加载配置文件
    pub fn load(&self) -> Result<RustCloudConfig, String> {
        let content = fs::read_to_string(&self.path)
            .map_err(|e| format!("Failed to read config file '{}': {}", self.path, e))?;
        
        self.parse_content(&content)
    }
    
    /// 解析配置内容
    pub fn parse_content(&self, content: &str) -> Result<RustCloudConfig, String> {
        match self.format {
            ConfigFormat::Toml => toml::from_str(content)
                .map_err(|e| format!("Failed to parse TOML config: {}", e)),
            ConfigFormat::Yaml => serde_yaml::from_str(content)
                .map_err(|e| format!("Failed to parse YAML config: {}", e)),
            ConfigFormat::Json => serde_json::from_str(content)
                .map_err(|e| format!("Failed to parse JSON config: {}", e)),
        }
    }
    
    /// 创建默认配置文件
    pub fn create_default_config(&self) -> Result<(), String> {
        let config = RustCloudConfig::create_example_config();
        let content = match self.format {
            ConfigFormat::Toml => toml::to_string_pretty(&config)
                .map_err(|e| format!("Failed to serialize TOML config: {}", e))?,
            ConfigFormat::Yaml => serde_yaml::to_string(&config)
                .map_err(|e| format!("Failed to serialize YAML config: {}", e))?,
            ConfigFormat::Json => serde_json::to_string_pretty(&config)
                .map_err(|e| format!("Failed to serialize JSON config: {}", e))?,
        };
        
        fs::write(&self.path, content)
            .map_err(|e| format!("Failed to write config file '{}': {}", self.path, e))
    }
}